﻿namespace MagicWatering.UI
{
    using System;
    using System.ComponentModel;
    using System.Reflection;
    using System.Windows.Forms;

    using MagicWatering.UI.Properties;

    /// <summary>
    ///     Framework for running application as a tray app.
    /// </summary>
    public class UiContext : ApplicationContext
    {
        #region Instance fields

        private readonly FormManager s_FormManager;

        /// <summary>
        /// a list of components to dispose when the context is disposed
        /// </summary>
        private IContainer components;

        private MainControlPanel m_mainPanel;

        /// <summary>
        /// the icon that sits in the system tray
        /// </summary>
        private NotifyIcon m_notifyIcon; 

        #endregion

        #region Constructors and Finalizers

        /// <summary>
        ///     This class should be created and passed into Application.Run( ... )
        /// </summary>
        public UiContext()
        {
            InitializeContext();
            s_FormManager = new FormManager(m_notifyIcon);
        }

        #endregion

        #region Methods

        /// <summary>
        ///     When the application context is disposed, dispose things like the notify icon.
        /// </summary>
        /// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && components != null)
            {
                components.Dispose();
            }
        }

        /// <summary>
        ///     If we are presently showing a form, clean it up.
        /// </summary>
        protected override void ExitThreadCore()
        {
            // before we exit, let forms clean themselves up.
            if (m_mainPanel != null)
            {
                m_mainPanel.Close();
            }

            // should remove lingering tray icon
            m_notifyIcon.Visible = false; 
            base.ExitThreadCore();
        }

        private void InitializeContext()
        {
            components = new Container();
            m_notifyIcon = new NotifyIcon(components)
            {
                ContextMenuStrip = new ContextMenuStrip(),
                Icon = Resources.logo,
                Text = Resources.ToolTip,
                Visible = true
            };
            m_notifyIcon.ContextMenuStrip.Opening += OnCreateContextMenu;
            m_notifyIcon.MouseDoubleClick += OnShowMainPanel;
            m_notifyIcon.MouseClick += OnOpenContextMenu;
        }

        private void ShowMainPanel()
        {
            if (m_mainPanel == null)
            {
                m_mainPanel = new MainControlPanel
                {
              //      FormManager = s_FormManager
                };
                m_mainPanel.Closed += OnPanelClosed; // avoid reshowing a disposed form
                m_mainPanel.Show();
            }
            else
            {
                m_mainPanel.Activate();
            }
        }

        private void OnCreateContextMenu(object sender, CancelEventArgs e)
        {
            e.Cancel = false;
            s_FormManager.BuildContextMenu(m_notifyIcon.ContextMenuStrip);
            m_notifyIcon.ContextMenuStrip.Items.Add(
                s_FormManager.ToolStripMenuItemWithHandler("Show &panel", OnShowMainPanel));
            m_notifyIcon.ContextMenuStrip.Items.Add(new ToolStripSeparator());
            m_notifyIcon.ContextMenuStrip.Items.Add(s_FormManager.ToolStripMenuItemWithHandler("&Exit", OnExit));
        }

        private void OnPanelClosed(object sender, EventArgs e)
        {
            m_mainPanel = null;
        }

        /// <summary>
        ///     When the exit menu item is clicked, make a call to terminate the ApplicationContext.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnExit(object sender, EventArgs e)
        {
            ExitThread();
        }

        private void OnOpenContextMenu(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                MethodInfo mi = typeof(NotifyIcon).GetMethod(
                    "ShowContextMenu",
                    BindingFlags.Instance | BindingFlags.NonPublic);
                mi.Invoke(m_notifyIcon, null);
            }
        }

        private void OnShowMainPanel(object sender, EventArgs e)
        {
            ShowMainPanel();
        }

        #endregion
    }
}